home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
demos
/
GL
/
newton
/
draw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
29KB
|
1,311 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* model/room drawing stuff
* Yossi Friedman, July 1988
*/
#include <stdio.h>
#include <gl.h>
#include <math.h>
#include "config.h"
#include "newton.h"
/*
* constants
*/
#define SURF_TOL (1. + 2. * (TOLERANCE - 1.))
#define SHADOW_TOL (1. + 1. * (TOLERANCE - 1.))
#define DIST (5. * HEIGHT)
/* RADIUS is the radius of the bounding circle of the room */
#define RADIUS (HEIGHT * (M_SQRT2 + 0.50))
#define GREY 18 /* wall color for bermuda mode */
static unsigned short halftone[] = { /* shadow blending pattern */
0x5555, 0xaaaa, 0x5555, 0xaaaa,
0x5555, 0xaaaa, 0x5555, 0xaaaa,
0x5555, 0xaaaa, 0x5555, 0xaaaa,
0x5555, 0xaaaa, 0x5555, 0xaaaa
};
#define HALFTONE 1
/*
* state variables
*/
static int new_M; /* was M changed since last frame? */
static int lighting; /* is the lighting model truned on? */
/*
* lighting model descriptors
*/
static float wall_material[MAX_LIGHTING_SIZE] = { WALL_MATERIAL };
static int wall_material_size = WALL_MATERIAL_SIZE;
#define WALL_MATERIAL_INDEX (MODEL_MATERIAL_INDEX + 1)
static float model_lmodel[MAX_LIGHTING_SIZE] = { MODEL_LMODEL };
static int model_lmodel_size = MODEL_LMODEL_SIZE;
static float light[MAX_LIGHTING_SIZE] = { POSITION, LIGHT_VECTOR, 0., LMNULL };
static int light_size = 6;
/*
* a vector pointing from the origin INTO the light source. The _M
* contains the light vector in the MODELING (room) coordinate system, and
* the _V -- in the VIEWING coordinate system. The idea is that the _V
* stays fixed.
*/
static float light_vec_V[3] = { LIGHT_VECTOR };
static float light_vec_M[3] = { LIGHT_VECTOR };
void lighting_on();
void lighting_off();
/*
* pinball mode variables, miscellaneaous variables
*/
static float red1 = RED1;
static float red2 = RED2;
static float green1 = GREEN1;
static float green2 = GREEN2;
static float blue1 = BLUE1;
static float blue2 = BLUE2;
static float vel_factor = 0.;
/*
* HEDGEHOG macro, for drawing normals (an essential debugging feature)
*/
#ifdef HEDGEHOG
# define draw_norm(v, norm) \
/* float v[3], norm[3] */ \
do { \
float vert[3]; \
if (mode == COLOR_MAP) \
color(BLUE); \
else \
RGBcolor(0, 0, 200); \
bgnline(); \
v3f(v); \
vert[0] = v[X] + 10.0*norm[X]; \
vert[1] = v[Y] + 10.0*norm[Y]; \
vert[2] = v[Z] + 10.0*norm[Z]; \
v3f(vert); \
if (mode == COLOR_MAP) \
color(YELLOW); \
else \
RGBcolor(200, 200, 0); \
vert[0] += 5.0*norm[X]; \
vert[1] += 5.0*norm[Y]; \
vert[2] += 5.0*norm[Z]; \
v3f(vert); \
endline(); \
} while (0)
#else /* HEDGEHOG*/
# define draw_norm(v, norm) do /* nothing */; while (0)
#endif /* HEDGEHOG */
initialize_draw()
{
int n, i, j;
/* initialize the relevant parts of the wall array */
# define wall_verts(WALL, x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4) \
wall[WALL].real_v[0][X] = 0. x1 HEIGHT; \
wall[WALL].real_v[0][Y] = 0. y1 HEIGHT; \
wall[WALL].real_v[0][Z] = 0. z1 HEIGHT; \
\
wall[WALL].real_v[1][X] = 0. x2 HEIGHT; \
wall[WALL].real_v[1][Y] = 0. y2 HEIGHT; \
wall[WALL].real_v[1][Z] = 0. z2 HEIGHT; \
\
wall[WALL].real_v[2][X] = 0. x3 HEIGHT; \
wall[WALL].real_v[2][Y] = 0. y3 HEIGHT; \
wall[WALL].real_v[2][Z] = 0. z3 HEIGHT; \
\
wall[WALL].real_v[3][X] = 0. x4 HEIGHT; \
wall[WALL].real_v[3][Y] = 0. y4 HEIGHT; \
wall[WALL].real_v[3][Z] = 0. z4 HEIGHT; \
\
wall[WALL].surf_v[0][X] = 0. x1 SURF_TOL * HEIGHT; \
wall[WALL].surf_v[0][Y] = 0. y1 SURF_TOL * HEIGHT; \
wall[WALL].surf_v[0][Z] = 0. z1 SURF_TOL * HEIGHT; \
\
wall[WALL].surf_v[1][X] = 0. x2 SURF_TOL * HEIGHT; \
wall[WALL].surf_v[1][Y] = 0. y2 SURF_TOL * HEIGHT; \
wall[WALL].surf_v[1][Z] = 0. z2 SURF_TOL * HEIGHT; \
\
wall[WALL].surf_v[2][X] = 0. x3 SURF_TOL * HEIGHT; \
wall[WALL].surf_v[2][Y] = 0. y3 SURF_TOL * HEIGHT; \
wall[WALL].surf_v[2][Z] = 0. z3 SURF_TOL * HEIGHT; \
\
wall[WALL].surf_v[3][X] = 0. x4 SURF_TOL * HEIGHT; \
wall[WALL].surf_v[3][Y] = 0. y4 SURF_TOL * HEIGHT; \
wall[WALL].surf_v[3][Z] = 0. z4 SURF_TOL * HEIGHT; \
\
vec_op(wall[WALL].surf_e[0], \
wall[WALL].surf_v[1], -, wall[WALL].surf_v[0]); \
\
vec_op(wall[WALL].surf_e[1], \
wall[WALL].surf_v[2], -, wall[WALL].surf_v[1]); \
\
vec_op(wall[WALL].surf_e[2], \
wall[WALL].surf_v[3], -, wall[WALL].surf_v[2]); \
\
vec_op(wall[WALL].surf_e[3], \
wall[WALL].surf_v[0], -, wall[WALL].surf_v[3])
wall_verts(WALL_TOP, +,+,-, +,+,+, -,+,+, -,+,-);
wall_verts(WALL_BOTTOM, +,-,-, -,-,-, -,-,+, +,-,+);
wall_verts(WALL_RIGHT, +,-,+, +,+,+, +,+,-, +,-,-);
wall_verts(WALL_LEFT, -,-,+, -,-,-, -,+,-, -,+,+);
wall_verts(WALL_FRONT, -,+,+, +,+,+, +,-,+, -,-,+);
wall_verts(WALL_BACK, -,+,-, -,-,-, +,-,-, +,+,-);
#undef wall_verts
wall[WALL_TOP] .axis = Y;
wall[WALL_TOP] .sign = 1.;
wall[WALL_TOP] .real_norm[X] = 0.;
wall[WALL_TOP] .real_norm[Y] = -1.;
wall[WALL_TOP] .real_norm[Z] = 0.;
wall[WALL_BOTTOM].axis = Y;
wall[WALL_BOTTOM].sign = -1.;
wall[WALL_BOTTOM].real_norm[X] = 0.;
wall[WALL_BOTTOM].real_norm[Y] = 1.;
wall[WALL_BOTTOM].real_norm[Z] = 0.;
wall[WALL_RIGHT] .axis = X;
wall[WALL_RIGHT] .sign = 1.;
wall[WALL_RIGHT] .real_norm[X] = -1.;
wall[WALL_RIGHT] .real_norm[Y] = 0.;
wall[WALL_RIGHT] .real_norm[Z] = 0.;
wall[WALL_LEFT] .axis = X;
wall[WALL_LEFT] .sign = -1.;
wall[WALL_LEFT] .real_norm[X] = 1.;
wall[WALL_LEFT] .real_norm[Y] = 0.;
wall[WALL_LEFT] .real_norm[Z] = 0.;
wall[WALL_FRONT] .axis = Z;
wall[WALL_FRONT] .sign = 1.;
wall[WALL_FRONT] .real_norm[X] = 0.;
wall[WALL_FRONT] .real_norm[Y] = 0.;
wall[WALL_FRONT] .real_norm[Z] = -1.;
wall[WALL_BACK] .axis = Z;
wall[WALL_BACK] .sign = -1.;
wall[WALL_BACK] .real_norm[X] = 0.;
wall[WALL_BACK] .real_norm[Y] = 0.;
wall[WALL_BACK] .real_norm[Z] = 1.;
for (n = 0; n < 6; n++)
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
wall[n].shadow[i][j] = ident_matrix[i][j];
/* define the pattern used for shadows */
defpattern(HALFTONE, 16, halftone);
}
long
open_model_window(char *title)
{
long wid;
keepaspect(5, 4);
foreground();
wid = winopen(title);
if (getgdesc(GD_BITS_NORM_SNG_RED) == 0)
{
system("inform 'Your system must support RGB mode to run newton'");
exit(1);
}
if (getgdesc(GD_BITS_NORM_ZBUFFER) == 0)
{
system("inform 'Your system must have a z-buffer to run newton'");
exit(1);
}
keepaspect(5, 4);
winconstraints();
wintitle("Newton Model");
doublebuffer();
if (mode == RGB)
RGBmode();
else
cmode();
gconfig();
zbuffer(TRUE);
#ifdef HAS_CZCLEAR
zfunction(ZF_GEQUAL);
/* lsetdepth(0x7fffff, 0x2000); */
lsetdepth((getgdesc(GD_ZMAX)), 0x2000);
#else /* HAS_CZCLEAR */
setdepth(0xc000, 0x3fff);
#endif /* HAS_CZCLEAR */
lmdef(DEFLMODEL, 1, model_lmodel_size, model_lmodel);
lmdef(DEFLIGHT, 1, light_size, light);
lmdef(DEFMATERIAL, WALL_MATERIAL_INDEX, wall_material_size, wall_material);
/* set the light vector */
normalize(light_vec_V);
apply(light_vec_M, light_vec_V, M_inv);
lighting_off();
lighting_on();
return(wid);
}
void
close_model_window(long wid)
{
lighting_off();
winclose(wid);
}
#ifdef CONFIG_FILE
initialize_config()
{
FILE *fp;
char line[200], *p;
int n, q;
float f;
fp = fopen(model_config, "r");
if (fp == NULL) {
fprintf(stderr, "newton: Could not open ");
if (model_config[0] == '/')
fprintf(stderr, "%s\n", model_config);
else
fprintf(stderr, "%s/%s\n", cwd(), model_config);
my_exit(1);
}
while (fgets(line, 200, fp) != NULL)
switch (line[0]) {
case '\n':
case '#':
continue;
case 'v':
sscanf(line + 1, "%f", &vel_factor);
break;
case 'r':
sscanf(line + 1, "%f %f", &red1, &red2);
break;
case 'g':
sscanf(line + 1, "%f %f", &green1, &green2);
break;
case 'b':
sscanf(line + 1, "%f %f", &blue1, &blue2);
break;
case 'l':
p = line + 1;
for (n = 0; sscanf(p, "%f%n", &f, &q) == 1; p += q) {
if (n == MAX_LIGHTING_SIZE) {
fprintf(stderr, "newton: Light too big\n");
my_exit(1);
}
light[n++] = f;
}
if (light[0] == POSITION) {
light_vec_V[X] = light[1];
light_vec_V[Y] = light[2];
light_vec_V[Z] = light[3];
}
light_size = n;
break;
case 'L':
p = line + 1;
for (n = 0; sscanf(p, "%f%n", &f, &q) == 1; p += q) {
if (n == MAX_LIGHTING_SIZE) {
fprintf(stderr, "newton: Lighting model too big\n");
my_exit(1);
}
model_lmodel[n++] = f;
}
model_lmodel_size = n;
break;
case 'J':
p = line + 1;
for (n = 0; sscanf(p, "%f%n", &f, &q) == 1; p += q) {
if (n == MAX_LIGHTING_SIZE) {
fprintf(stderr, "newton: Default model material too big\n");
my_exit(1);
}
default_model_material[n++] = f;
}
default_model_material_size = n;
break;
case 'W':
p = line + 1;
for (n = 0; sscanf(p, "%f%n", &f, &q) == 1; p += q) {
if (n == MAX_LIGHTING_SIZE) {
fprintf(stderr, "newton: Wall material too big\n");
my_exit(1);
}
wall_material[n++] = f;
}
wall_material_size = n;
break;
default:
fprintf(stderr, "newton: Syntax error in config file: \"%s\"\n", line);
my_exit(1);
}
}
#endif /* CONFIG_FILE */
rotate_graphics(Angle alpha,char axis)
{
/* adjust M */
pushmatrix();
loadmatrix(ident_matrix);
rotate(alpha, axis);
multmatrix(M);
getmatrix(M);
popmatrix();
/* adjust M inverse */
pushmatrix();
loadmatrix(M_inv);
rotate(-alpha, axis);
getmatrix(M_inv);
popmatrix();
new_M = 1;
/* set the light vector */
apply(light_vec_M, light_vec_V, M_inv);
}
draw_everything()
{
swapbuffers();
#ifdef HAS_CZCLEAR
czclear(0, 0);
#else /* HAS_CZCLEAR */
if (mode == COLOR_MAP)
color(BLACK);
else
RGBcolor(0, 0, 0);
clear();
zclear();
#endif /* HAS_CZCLEAR */
if (new_M) {
loadmatrix(ident_matrix);
lookat(0.,0.,DIST, 0.,0.,0., 0);
multmatrix(M);
new_M = 0;
}
draw_room();
(*draw_model)();
if (springs_too)
draw_springs();
}
draw_room()
{
void (*actual_draw_wall)(int);
if (mode == RGB)
actual_draw_wall = draw_wall;
else
actual_draw_wall = draw_plain_wall;
/* draw the wall surfaces */
if (M[Y][Z] < HEIGHT/DIST)
(*actual_draw_wall)(WALL_TOP);
if (M[Y][Z] > -HEIGHT/DIST)
(*actual_draw_wall)(WALL_BOTTOM);
if (M[X][Z] < HEIGHT/DIST)
(*actual_draw_wall)(WALL_RIGHT);
if (M[X][Z] > -HEIGHT/DIST)
(*actual_draw_wall)(WALL_LEFT);
if (M[Z][Z] < HEIGHT/DIST)
(*actual_draw_wall)(WALL_FRONT);
if (M[Z][Z] > -HEIGHT/DIST)
(*actual_draw_wall)(WALL_BACK);
/* draw the frame itself */
if (mode == COLOR_MAP)
color(BLUE);
else
RGBcolor(50, 100, 255);
#ifdef HAS_CZCLEAR
zfunction(ZF_ALWAYS);
#endif /* HAS_CZCLEAR */
bgnline();
v3f(wall[WALL_BOTTOM].surf_v[0]);
v3f(wall[WALL_BOTTOM].surf_v[1]);
v3f(wall[WALL_BOTTOM].surf_v[2]);
v3f(wall[WALL_BOTTOM].surf_v[3]);
v3f(wall[WALL_BOTTOM].surf_v[0]);
v3f(wall[WALL_TOP].surf_v[0]);
v3f(wall[WALL_TOP].surf_v[3]);
v3f(wall[WALL_TOP].surf_v[2]);
v3f(wall[WALL_TOP].surf_v[1]);
v3f(wall[WALL_TOP].surf_v[0]);
endline();
bgnline();
v3f(wall[WALL_BOTTOM].surf_v[1]);
v3f(wall[WALL_TOP].surf_v[3]);
endline();
bgnline();
v3f(wall[WALL_BOTTOM].surf_v[2]);
v3f(wall[WALL_TOP].surf_v[2]);
endline();
bgnline();
v3f(wall[WALL_BOTTOM].surf_v[3]);
v3f(wall[WALL_TOP].surf_v[1]);
endline();
#ifdef HAS_CZCLEAR
zfunction(ZF_GEQUAL);
#endif /* HAS_CZCLEAR */
}
void
draw_lighted_wall(int n)
{
struct wall *w = &wall[n];
float e[3], pos[3], f_norm[4][3], vel_correction;
float rotm[4][4], rotm_inv[4][4], cos_beta, sin_beta;
int axis1, axis2, axis3;
int t;
lighting_on();
lmbind(MATERIAL, WALL_MATERIAL_INDEX);
axis1 = w->axis;
if (w->penetrated) {
/*
* move pos slightly outward, to prevent annoying artifacts
*/
pos[X] = w->atom->pos[X];
pos[Y] = w->atom->pos[Y];
pos[Z] = w->atom->pos[Z];
pos[axis1] *= SURF_TOL;
vel_correction = vel_factor * w->atom->vel[w->axis];
if (vel_correction < 0)
vel_correction = -vel_correction;
pos[w->axis] += w->sign * vel_correction;
/*
* calculate the normals to each triangular face
*/
vec_op(e, w->surf_v[0], -, pos);
cross(f_norm[0], e, w->surf_e[0]);
normalize(f_norm[0]);
vec_op(e, w->surf_v[1], -, pos);
cross(f_norm[1], e, w->surf_e[1]);
normalize(f_norm[1]);
vec_op(e, w->surf_v[2], -, pos);
cross(f_norm[2], e, w->surf_e[2]);
normalize(f_norm[2]);
vec_op(e, w->surf_v[3], -, pos);
cross(f_norm[3], e, w->surf_e[3]);
normalize(f_norm[3]);
/*
* calculate the normals at the vertices
*/
vec_op(w->surf_norm[0], f_norm[3], +, f_norm[0]);
normalize(w->surf_norm[0]);
vec_op(w->surf_norm[1], f_norm[0], +, f_norm[1]);
normalize(w->surf_norm[1]);
vec_op(w->surf_norm[2], f_norm[1], +, f_norm[2]);
normalize(w->surf_norm[2]);
vec_op(w->surf_norm[3], f_norm[2], +, f_norm[3]);
normalize(w->surf_norm[3]);
vec_op(w->surf_norm[4], f_norm[0], +, f_norm[1]);
vec_op(w->surf_norm[4], w->surf_norm[4], +, f_norm[2]);
vec_op(w->surf_norm[4], w->surf_norm[4], +, f_norm[3]);
normalize(w->surf_norm[4]);
/*
* draw the triangles
*/
bgnpolygon();
n3f(w->surf_norm[0]); v3f(w->surf_v[0]);
n3f(w->surf_norm[1]); v3f(w->surf_v[1]);
n3f(w->surf_norm[4]); v3f(pos);
endpolygon();
bgnpolygon();
n3f(w->surf_norm[1]); v3f(w->surf_v[1]);
n3f(w->surf_norm[2]); v3f(w->surf_v[2]);
n3f(w->surf_norm[4]); v3f(pos);
endpolygon();
bgnpolygon();
n3f(w->surf_norm[2]); v3f(w->surf_v[2]);
n3f(w->surf_norm[3]); v3f(w->surf_v[3]);
n3f(w->surf_norm[4]); v3f(pos);
endpolygon();
bgnpolygon();
n3f(w->surf_norm[3]); v3f(w->surf_v[3]);
n3f(w->surf_norm[0]); v3f(w->surf_v[0]);
n3f(w->surf_norm[4]); v3f(pos);
endpolygon();
draw_norm(w->surf_v[0], w->surf_norm[0]);
draw_norm(w->surf_v[1], w->surf_norm[1]);
draw_norm(w->surf_v[2], w->surf_norm[2]);
draw_norm(w->surf_v[3], w->surf_norm[3]);
draw_norm(pos, w->surf_norm[4]);
if (shadows_too == 0)
goto finale;
/*
* check if a shadow is cast on the triangles. The condition is that
* the normal to the triangle has a positive component in the direction
* of the light.
*/
for (t = 0; t < 4; t++ )
if (dot(light_vec_M, f_norm[t]) > 0.) {
lighting_off();
axis2 = (axis1 + 1) % 3;
if (w->surf_v[t][axis2] != w->surf_v[(t+1)%4][axis2])
axis2 = (axis1 + 2) % 3;
axis3 = (X + Y + Z) - (axis1 + axis2);
/*
* the following code generates a rotation matrix
* of beta degrees around axis3
*/
cos_beta = dot(f_norm[t], w->real_norm);
sin_beta = sqrt(1. - cos_beta * cos_beta);
cross(e, f_norm[t], w->real_norm);
if (e[axis3] < 0.)
sin_beta = -sin_beta;
memcpy(rotm, ident_matrix, 4 * 4 *sizeof(float));
memcpy(rotm_inv, ident_matrix, 4 * 4 *sizeof(float));
rotm[axis1][axis1] =
rotm[axis2][axis2] =
rotm_inv[axis1][axis1] =
rotm_inv[axis2][axis2] = cos_beta;
if (axis3 != Y)
if (axis1 < axis2) {
rotm[axis1][axis2] = sin_beta;
rotm[axis2][axis1] = -sin_beta;
rotm_inv[axis1][axis2] = -sin_beta;
rotm_inv[axis2][axis1] = sin_beta;
}
else {
rotm[axis2][axis1] = sin_beta;
rotm[axis1][axis2] = -sin_beta;
rotm_inv[axis2][axis1] = -sin_beta;
rotm_inv[axis1][axis2] = sin_beta;
}
else /* axis3 is Y */
if (axis1 < axis2) {
rotm[axis1][axis2] = -sin_beta;
rotm[axis2][axis1] = sin_beta;
rotm_inv[axis1][axis2] = sin_beta;
rotm_inv[axis2][axis1] = -sin_beta;
}
else {
rotm[axis2][axis1] = -sin_beta;
rotm[axis1][axis2] = sin_beta;
rotm_inv[axis2][axis1] = sin_beta;
rotm_inv[axis1][axis2] = -sin_beta;
}
/* need to rotate the light vector as well */
apply(e, light_vec_M, rotm);
w->shadow[axis1][axis1] = 0.;
w->shadow[axis1][axis2] = - e[axis2] /
e[axis1];
w->shadow[axis1][axis3] = - e[axis3] /
e[axis1];
e[axis1] = w->atom->pos[axis1] * SHADOW_TOL;
e[axis2] = w->atom->pos[axis2];
e[axis3] = w->atom->pos[axis3];
translate(
e[X],
e[Y],
e[Z]
);
multmatrix(rotm_inv);
multmatrix(w->shadow);
multmatrix(rotm);
translate(
- w->atom->pos[X],
- w->atom->pos[Y],
- w->atom->pos[Z]
);
draw_shadows();
}
lighting_on();
}
else {
bgnpolygon();
n3f(w->real_norm);
v3f(w->surf_v[0]);
v3f(w->surf_v[1]);
v3f(w->surf_v[2]);
v3f(w->surf_v[3]);
endpolygon();
#ifdef HEDGEHOG
axis2 = (axis1 + 1) % 3;
axis3 = (axis1 + 2) % 3;
e[axis1] = w->sign * HEIGHT;
e[axis2] = e[axis3] = 0.;
draw_norm(e, w->real_norm);
#endif /* HEDGEHOG */
if (shadows_too == 0)
goto finale;
/*
* check if a shadow is cast on the wall. The condition is that
* the normal to the wall has a positive component in the direction
* of the light.
*/
if (dot(light_vec_M, w->real_norm) > 0.) {
axis2 = (axis1 + 1) % 3;
axis3 = (axis1 + 2) % 3;
lighting_off();
w->shadow[axis1][axis1] = 0.;
w->shadow[axis1][axis2] = - light_vec_M[axis2] /
light_vec_M[axis1];
w->shadow[axis1][axis3] = - light_vec_M[axis3] /
light_vec_M[axis1];
e[axis1] = w->sign * HEIGHT * SHADOW_TOL;
e[axis2] = e[axis3] = 0.;
translate(e[X], e[Y], e[Z]);
multmatrix(w->shadow);
e[axis1] = - w->sign * HEIGHT;
translate(e[X], e[Y], e[Z]);
draw_shadows();
lighting_on();
}
}
finale:
hide_wall_exterior(n);
}
void
draw_pinball_wall(int n)
{
struct wall *w = &wall[n];
float pos[3];
float basic_color[3], color[3];
basic_color[0] = red2;
basic_color[1] = green2;
basic_color[2] = blue2;
if (w->penetrated) {
/*
* calculate the colors
*/
color[0] = red1 * w->depth + red2;
if (color[0] > 1.0)
color[0] = 1.0;
color[1] = green1 * w->depth + green2;
if (color[1] > 1.0)
color[1] = 1.0;
color[2] = blue1 * w->depth + blue2;
if (color[2] > 1.0)
color[2] = 1.0;
/*
* move pos slightly outward, to prevent annoying artifacts
*/
pos[X] = w->atom->pos[X];
pos[Y] = w->atom->pos[Y];
pos[Z] = w->atom->pos[Z];
pos[w->axis] *= SURF_TOL;
/*
* draw the triangles
*/
bgnpolygon();
c3f(basic_color); v3f(w->surf_v[0]);
c3f(basic_color); v3f(w->surf_v[1]);
c3f(color); v3f(pos);
endpolygon();
bgnpolygon();
c3f(basic_color); v3f(w->surf_v[1]);
c3f(basic_color); v3f(w->surf_v[2]);
c3f(color); v3f(pos);
endpolygon();
bgnpolygon();
c3f(basic_color); v3f(w->surf_v[2]);
c3f(basic_color); v3f(w->surf_v[3]);
c3f(color); v3f(pos);
endpolygon();
bgnpolygon();
c3f(basic_color); v3f(w->surf_v[3]);
c3f(basic_color); v3f(w->surf_v[0]);
c3f(color); v3f(pos);
endpolygon();
}
else {
bgnpolygon();
c3f(basic_color);
v3f(w->surf_v[0]);
v3f(w->surf_v[1]);
v3f(w->surf_v[2]);
v3f(w->surf_v[3]);
endpolygon();
}
hide_wall_exterior(n);
}
void
draw_plain_wall(int n)
{
struct wall *w = &wall[n];
float pos[3];
if (w->penetrated) {
/*
* move pos slightly outward, to prevent annoying artifacts
*/
pos[X] = w->atom->pos[X] * SURF_TOL;
pos[Y] = w->atom->pos[Y] * SURF_TOL;
pos[Z] = w->atom->pos[Z] * SURF_TOL;
/*
* draw the triangles
*/
bgnpolygon();
color(GREY); v3f(w->surf_v[0]);
color(GREY); v3f(w->surf_v[1]);
color(GREY); v3f(pos);
endpolygon();
bgnpolygon();
color(GREY); v3f(w->surf_v[1]);
color(GREY); v3f(w->surf_v[2]);
color(GREY); v3f(pos);
endpolygon();
bgnpolygon();
color(GREY); v3f(w->surf_v[2]);
color(GREY); v3f(w->surf_v[3]);
color(GREY); v3f(pos);
endpolygon();
bgnpolygon();
color(GREY); v3f(w->surf_v[3]);
color(GREY); v3f(w->surf_v[0]);
color(GREY); v3f(pos);
endpolygon();
}
else {
bgnpolygon();
color(GREY);
v3f(w->surf_v[0]);
v3f(w->surf_v[1]);
v3f(w->surf_v[2]);
v3f(w->surf_v[3]);
endpolygon();
}
hide_wall_exterior(n);
}
/*
* hide the back side of the wall, so that the body is not seen
* penetrating the wall
*/
hide_wall_exterior(int n)
{
struct wall *w = &wall[n];
float corner[4][3];
int i, j;
for (i = 0; i < 4; i++) {
for (j = X; j <= Z; j++)
corner[i][j] = w->surf_v[i][j];
corner[i][w->axis] += w->sign * HEIGHT;
}
backbuffer(FALSE);
bgnpolygon();
v3f(w->surf_v[0]);
v3f(corner[0]);
v3f(corner[1]);
v3f(w->surf_v[1]);
endpolygon();
bgnpolygon();
v3f(w->surf_v[1]);
v3f(corner[1]);
v3f(corner[2]);
v3f(w->surf_v[2]);
endpolygon();
bgnpolygon();
v3f(w->surf_v[2]);
v3f(corner[2]);
v3f(corner[3]);
v3f(w->surf_v[3]);
endpolygon();
bgnpolygon();
v3f(w->surf_v[3]);
v3f(corner[3]);
v3f(corner[0]);
v3f(w->surf_v[0]);
endpolygon();
backbuffer(TRUE);
}
void
lighting_off()
{
if (lighting == 0)
return;
lmbind(MATERIAL, 0);
lmbind(LMODEL, 0);
lmbind(LIGHT0, 0);
mmode(MSINGLE);
loadmatrix(ident_matrix);
perspective(400, 5./4., DIST - RADIUS, DIST + RADIUS);
lookat(0.,0.,DIST, 0.,0.,0., 0);
multmatrix(M);
lighting = 0;
}
void
lighting_on()
{
if (lighting == 1)
return;
#ifdef CLOVER1 /* 4D gl bug */
loadmatrix(ident_matrix);
#endif /* CLOVER1 */
mmode(MVIEWING);
loadmatrix(ident_matrix);
perspective(400, 5./4., DIST - RADIUS, DIST + RADIUS);
lookat(0.,0.,DIST, 0.,0.,0., 0);
lmbind(LIGHT0, 1);
lmbind(LMODEL, 1);
multmatrix(M);
lighting = 1;
}
draw_shadows()
{
Surf *sp;
int i;
zwritemask(0);
setpattern(HALFTONE);
if (mode == COLOR_MAP)
color(BLACK);
else
RGBcolor(0, 0, 0);
for (sp = model_surfs; sp < end_model_surfs TOTAL; sp++) {
bgnpolygon();
for (i = 0; i < sp->n; i++)
v3f((sp->vert[i])->pos);
endpolygon();
}
setpattern(0);
zwritemask(0xffffff);
}
void
draw_flat_surfs()
{
float *v, *norm;
Surf *sp;
int i, n;
/*
* PHASE I: compute the normals
*/
SLAVE_FUNC(DRAW_FLAT_SURFS_1);
draw_flat_surfs_1(model_surfs, end_model_surfs MASTER);
WAIT_FOR_SLAVE();
/*
* PHASE II: draw surfaces
*/
#ifdef HAS_BLENDING
if (alpha_blended) {
blendfunction(BF_SA, BF_MSA);
zwritemask(0);
}
#endif /* HAS_BLENDING */
lmbind(MATERIAL, MODEL_MATERIAL_INDEX);
for (sp = model_surfs; sp < end_model_surfs TOTAL; sp++) {
n = sp->n;
bgnpolygon();
for (i = 0; i < n; i++) {
v = (sp->vert[i])->pos;
norm = &(sp->norm)[4*i];
n3f(norm);
v3f(v);
}
endpolygon();
#ifdef HEDGEHOG
for (i = 0; i < n; i++) {
v = (sp->vert[i])->pos;
norm = &(sp->norm)[4*i];
draw_norm(v, norm);
}
#endif /* HEDGEHOG */
}
#ifdef HAS_BLENDING
if (alpha_blended) {
blendfunction(BF_ONE, BF_ZERO);
zwritemask(0xffffff);
}
#endif /* HAS_BLENDING */
}
draw_flat_surfs_1(Surf *start, Surf *finish)
{
float *v, *nv, *e1, *e2, *tmp, buf[2][3], *norm;
Surf *sp;
int i, n;
e1 = &buf[0][0];
e2 = &buf[1][0];
for (sp = start; sp < finish; sp++) {
n = sp->n;
v = (sp->vert[0])->pos;
vec_op(e1, v, -, (sp->vert[n-1])->pos);
for (i = 1; i < n; i++) {
nv = (sp->vert[i])->pos;
norm = &sp->norm[4*i];
vec_op(e2, nv, -, v);
cross(norm, e1, e2);
normalize(norm);
tmp = e1; e1 = e2; e2 = tmp;
v = nv;
}
nv = (sp->vert[0])->pos;
norm = &sp->norm[0];
vec_op(e2, nv, -, v);
cross(norm, e1, e2);
normalize(norm);
}
}
void
draw_smooth_surfs()
{
Surf *sp;
Atom **p;
int n;
/*
* PHASE I: clear all normals
*/
SLAVE_FUNC(DRAW_SMOOTH_SURFS_1);
draw_smooth_surfs_1(model_atoms, end_model_atoms MASTER);
WAIT_FOR_SLAVE();
/*
* PHASE II: accumulate for each atom all the normals to the surfaces
* it participates in
*/
SLAVE_FUNC(DRAW_SMOOTH_SURFS_2);
draw_smooth_surfs_2(model_surfs, end_model_surfs MASTER MASTER_PARAM);
WAIT_FOR_SLAVE();
/*
* PHASE III: normalize the cumulative normals
*/
SLAVE_FUNC(DRAW_SMOOTH_SURFS_3);
draw_smooth_surfs_3(model_atoms, end_model_atoms MASTER);
WAIT_FOR_SLAVE();
/*
* PHASE IV: draw the surfaces
*/
#ifdef HAS_BLENDING
if (alpha_blended) {
blendfunction(BF_SA, BF_MSA);
zwritemask(0);
}
#endif /* HAS_BLENDING */
lmbind(MATERIAL, MODEL_MATERIAL_INDEX);
for (sp = model_surfs; sp < end_model_surfs TOTAL; sp++) {
n = sp->n;
bgnpolygon();
for (p = &sp->vert[0]; p < &sp->vert[n]; p++) {
n3f((*p)->norm MASTER);
v3f((*p)->pos);
}
endpolygon();
#ifdef HEDGEHOG
for (p = &sp->vert[0]; p < &sp->vert[n]; p++)
draw_norm((*p)->pos, (*p)->norm MASTER);
#endif /* HEDGEHOG */
}
#ifdef HAS_BLENDING
if (alpha_blended) {
blendfunction(BF_ONE, BF_ZERO);
zwritemask(0xffffff);
}
#endif /* HAS_BLENDING */
}
draw_smooth_surfs_1(Atom *start, Atom *finish)
{
Atom *ap;
for (ap = start; ap < finish; ap++) {
#ifdef MP
{
int i;
for (i = 1; i < nproc; i++)
ap->norm [i] [X] =
ap->norm [i] [Y] =
ap->norm [i] [Z] = 0.;
}
#endif /* MP */
ap->norm MASTER [X] =
ap->norm MASTER [Y] =
ap->norm MASTER [Z] = 0.;
}
}
draw_smooth_surfs_2(Surf *start, Surf *finish, CPU_PARAM_TYPE)
{
float *v, *nv, *e1, *e2, *tmp, buf[2][3], norm[3];
Surf *sp;
Atom **p;
int n;
e1 = &buf[0][0];
e2 = &buf[1][0];
for (sp = start; sp < finish; sp++) {
n = sp->n;
v = (sp->vert[0])->pos;
vec_op(e1, v, -, (sp->vert[n-1])->pos);
for (p = &sp->vert[1]; p < &sp->vert[n]; p++) {
nv = (*p)->pos;
vec_op(e2, nv, -, v);
cross(norm, e1, e2);
normalize(norm);
vec_op(p[-1]->norm CPU, p[-1]->norm CPU, +, norm);
tmp = e1; e1 = e2; e2 = tmp;
v = nv;
}
nv = (sp->vert[0])->pos;
vec_op(e2, nv, -, v);
cross(norm, e1, e2);
normalize(norm);
vec_op(p[-1]->norm CPU, p[-1]->norm CPU, +, norm);
}
}
draw_smooth_surfs_3(Atom *start, Atom *finish)
{
Atom *ap;
for (ap = start; ap < finish; ap++) {
#ifdef MP
{
int i;
for (i = 1; i < nproc; i++)
vec_op(ap->norm MASTER,
ap->norm MASTER, +, ap->norm[i]);
}
#endif /* MP */
normalize(ap->norm MASTER);
}
}
void
draw_springs()
{
Spring *spring;
if (mode == COLOR_MAP)
color(YELLOW);
else
RGBcolor(200, 200, 20);
for (spring = model_springs; spring < end_model_springs TOTAL; spring++) {
bgnline();
v3f(spring->from->pos);
v3f(spring->to->pos);
endline();
}
}